<?php
/* MyMeeting is an online meeting management software.
 * Copyright (C) 2009 Government Of Malaysia
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * @author: Abdullah Zainul Abidin, Nuhaa All Bakry
 *          Eavay Javay Barnad, Sarogini Muniyandi, Teow Jit Huan
 *
 */

class Meeting extends AppModel {

    /**
     * Defining the name of model
     *
     */
    var $name = 'Meeting';
    /**
     * Defining the name of the table
     *
     */
    var $useTable = 'meetings';
    /**
     * Displaying meeting short name
     *
     */
    var $displayField = 'meeting_num';
    /**
     * Defining behavior in the model
     *
     */
    var $actsAs = array('Comment','MultiFile','Containable');

    //validation
    /**
     * Validating the fields in meeting model
     *
     */
    var $validate = array(
        'meeting_title' =>array(
            'required'=>array(
                'rule' => 'notEmpty'
            )
        ),
        'meeting_date'=>array(
            'required'=>array(
                'rule' => 'notEmpty'
            )
        ),
        'venue'=>array(
            'required'=>array(
                'rule' => 'notEmpty'
            )
        ),
    );

    //The Associations below have been created with all possible keys, those that are not needed can be removed
    /**
     * Building assosiations betweeen models
     *
     */
    var $belongsTo = array(
        'Committee' => array(
            'className' => 'Committee',
            'foreignKey' => 'committee_id',
            'conditions' => '',
            'fields' => '',
            'order' => '')
        );

    /**
     * Building assosiations betweeen models
     *
     */
    var $hasMany = array(
        'Decision' => array(
            'className' => 'Decision',
            'foreignKey' => 'meeting_id',
            'dependent' => false,
            'conditions' => array('deleted'=>0),
            'fields' => '',
            'order' => '',
            'limit' => '',
            'offset' => '',
            'exclusive' => '',
            'finderQuery' => '',
            'counterQuery' => ''),
        'Notification' => array(
            'className' => 'Notification',
            'foreignKey' => 'meeting_id',
            'dependent' => false,
            'conditions' => '',
            'fields' => 'notification_sent,type',
            'order' => '',
            'limit' => '',
            'offset' => '',
            'exclusive' => '',
            'finderQuery' => '',
            'counterQuery' => ''),
        'Todo' => array(
            'className' => 'Meetingtodo',
            'foreignKey' => 'meeting_id',
            'dependent' => false,
            'conditions' => '',
            'fields' => '',
            'order' => '',
            'limit' => '',
            'offset' => '',
            'exclusive' => '',
            'finderQuery' => '',
            'counterQuery' => '')
        );

    /**
     * Building assosiations betweeen models
     *
     */
    var $hasAndBelongsToMany = array(
        'User'=>array(
            'className' => 'User',
            'joinTable' => 'attendances',
            'foreignKey' => 'meeting_id',
            'associationForeignKey' => 'user_id',
            'unique' => true,
            'conditions' => array('Attendance.deleted'=>0),
            'fields' => '',
            'order' => '',
            'limit' => '',
            'offset' => '',
            'finderQuery' => '',
            'deleteQuery' => '',
            'insertQuery' => ''
        )
    );

    /**
     * Getting all the related users per meeting defined by the meeting_id
     * $param meeting_id finds all the related users per meeting
     */
    function getUsersPerMeeting($meeting_id) {
        $o = $this->Attendance->find('all',array(
            'conditions'=>array('meeting_id'=>$meeting_id)
        ));
        return $o;                                  
    }

    /**
     * Return various data about the user (user_id) regarding a meeting (meeting_id)
     * @return an array with invited, attended, role, and groups
     */
    function userData($user_id,$meeting_id=null){
        if($meeting_id){
            $toret=$this->Committee->userData($user_id,$this->getCommitteeId($meeting_id));
            $userdat=$this->Attendance->find('first',array('conditions'=>array('meeting_id'=>$meeting_id,'user_id'=>$user_id)));
            if(count($userdat['Attendance'])){
                $toret['invited']=true;
                $toret['attended']=$userdat['Attendance']['attended'];
            }
            else{
                $toret['invited']=false;
                $toret['attended']=false;
            }
            return $toret;
        }
        return false;
    }

    /**
     * Getting all the related committees defined by the meeting_id
     * $param meeting_id finds all the committee
     */
    function getCommitteeId($meeting_id){
        $data=$this->getData(array('committee_id'),array('Meeting.id'=>$meeting_id));
        return $data[0]['Meeting']['committee_id'];
    }

    /**
     * Finding fields in the template that matches the  marker
     * 
     */
    function templatefield($field,$template){
        $template=" ".$template;
        $start=strpos(low($template),'%'.low($field));
        if(!empty($start)){
            $end=strrpos(low($template),low($field).''.low($field))+2;
        
            if(empty($end)){
                $end=strlen($template);
            }
            $toret['length']=$end-$start;  
            $toret['pos']=$start-1; 
        
            $toret['field']=substr($template,$start+1,$toret['length']-1);
        }
		if(isset($toret['field'])){
			return $toret;
		}
        
		return null;
    }

    function replacetemplatedate($template,$fyear,$fmonth){
        if($fyear){
            if($fyear['length']==5) $ydat=date("Y");
            elseif($fyear['length']==3) $ydat=date("y");
            $template=str_replace('%'.$fyear['field'],$ydat,$template);
        }
        if($fmonth){
            if($fmonth['length']==3) $mdat=date("m");
            elseif($fmonth['length']==4) $mdat=date("M");
            $template=str_replace('%'.$fmonth['field'],$mdat,$template);
        }
        return $template;
    }

    /**
     * Getting all the next numbers (x,y,m) in the meeting for the the defined committee_id
     * $param committee_id finds all the next numbers in the meeting
     */
    function nextnumber($committee_id){
        $template=$this->Committee->field('meeting_num_template',array('id'=>$committee_id));
        $fnum=$this->templatefield('x',$template);
        $fyear=$this->templatefield('y',$template);
        $fmonth=$this->templatefield('m',$template);
        if($fnum){  //inside the template there is a placeholder for numbers
            $template=$this->replacetemplatedate($template,$fyear,$fmonth);
            $btemplate=str_replace('%'.$fnum['field'],'%',$template);
            $db =& ConnectionManager::getDataSource($this->useDbConfig);
            $latestnum=$this->query('SELECT Meeting.meeting_num from '.$db->fullTableName('meetings').' as Meeting where Meeting.committee_id='.$committee_id.' and Meeting.meeting_num like \''.$btemplate.'\' and Meeting.deleted!=\'1\' order by length(Meeting.meeting_num) desc,Meeting.meeting_num desc limit 1');
            $dnum=0;
            $dnum=0;
            if(isset($latestnum[0])){
                $dlatest=$latestnum[0]['Meeting']['meeting_num'];
                for($i=$fnum['pos'];$i<strlen($dlatest);$i++){
                    $c=substr($dlatest,$i,1);
                    if(is_numeric($c)){
                        $dnum.=$c;
                    }
                    else{
                        break;
                    }
                }
            }
            $dnum+=1;
            return str_replace('%'.$fnum['field'],$dnum,$template);
        }
        $latestnum=$this->find('first',array('limit'=>1,'order'=>'meeting_num desc','conditions'=>array('committee_id'=>$committee_id)));
        return $latestnum['Meeting']['meeting_num'];
    }
    
    function meetingtitle($committee_id) {
        $meeting = $this->Committee->find(array('Committee.id'=>$committee_id));
        //debug($meeting);
        $defaulttitle = $meeting['Committee']['meeting_title_template'];
        $defaulttitle = str_replace('%committeeshort',$meeting['Committee']['short_name'],$defaulttitle);
        $defaulttitle = str_replace('%committeelong',$meeting['Committee']['name'],$defaulttitle);
        return $defaulttitle;
    }
    
    /**
     * Describe sendEmail 
     * send email
     * @param $meeting
     * @param $template
     * @param $user --recipient
     * @param $date
     * @return null
     */
    function sendEmail($meeting=null,$template,$user,$date){
        $this->Notification->create();
        if(!empty($meeting['id'])){
            $notification['meeting_id']=$meeting['id'];
        }
        if(!empty($date)){
            $notification['notification_date']=$date;
        }else{
            $notification['notification_date']=date("Y-m-d H:i:s");
        }
        $notification['type']=$template['Template']['type'];
        $notification['message_title']=$template['Template']['title'];
        $notification['to']=$user['email'];
        if($template['Template']['model']!='SystemOnly'){
            $notification['cc']=$user['cc_email'];
        }
        if($template['Template']['type'] == 'invite'||$template['Template']['type'] == 'uninvite'||$template['Template']['type'] == 'change'){
            $notification['data']="'meeting_date'='".$meeting['meeting_date']."','venue'='".$meeting['venue']."'";
        }
        $title = $this->User->Title->find('first',array('conditions'=>array('id'=>$user['title_id'])));
        $user['name']=$title['Title']['short_name'].' '.$user['name'];
        $notification['message']=$this->replacetemplate($template['Template']['template'],$user);
        $this->Notification->save($notification);
    }
    
    function attendancelist($meetingId, $committee){
        $committeeID = $this->query("SELECT id FROM committees WHERE short_name='".$committee."'");
        $committeeID = $committeeID[0]['committees']['id'];
        $attendanceslist = $this->query("SELECT Attendance.*, User.id, User.name FROM attendances Attendance LEFT JOIN users User ON Attendance.user_id = User.id LEFT JOIN memberships membership ON membership.user_id = User.id AND membership.committee_id = ".$committeeID." WHERE Attendance.user_id!=0 AND Attendance.deleted = 0 AND Attendance.meeting_id =".$meetingId." ORDER BY membership.order_id");
        $attendanceslist = $this->UserLevelReorder($attendanceslist);
        return $attendanceslist;
    }

    function userlevel($userlv){
        $UserLevelList = array(
            '1'=>__('Secretariat',true),
            '2'=>__('Chairperson',true),
            '3'=>__('Member',true),
            '4'=>__('Member (external)',true)
        );
        if ( isset($UserLevelList[$userlv]) ) {
            return $UserLevelList[$userlv];
        } else {
            return "unknow";
        }
        
    }

    
    function UserLevelReorder($attendanceslists){
        $chairperson = $secretariat = $members = array();   
        $numlist = 0;       
        foreach ($attendanceslists as $attendanceslist) {;
            
            if ( $attendanceslist['Attendance']['attend_as'] == "2" ) {
                $attendanceslists[$numlist]['User']['name']=$attendanceslists[$numlist]['User']['name']."&nbsp;&nbsp;(&nbsp;".$this->userlevel($attendanceslist['Attendance']['attend_as'])."&nbsp;)";          
                array_push($chairperson, $attendanceslists[$numlist]);
            } elseif ( $attendanceslist['Attendance']['attend_as'] == "1" ) {
                $attendanceslists[$numlist]['User']['name']=$attendanceslists[$numlist]['User']['name']."&nbsp;&nbsp;(&nbsp;".$this->userlevel($attendanceslist['Attendance']['attend_as'])."&nbsp;)";
                array_push($secretariat, $attendanceslists[$numlist]);
            } else {
                array_push($members, $attendanceslists[$numlist]);
            }
            $numlist++;
        }
        return array_merge($chairperson, $members, $secretariat);

    }
    
    function create_cal($committee_id){
        require_once('vendors/iCalcreator.class.php');
        $meetings=$this->find('all',array('conditions'=>array('Meeting.committee_id'=>$committee_id,'Meeting.deleted'=>0),'order'=>'meeting_date DESC'));
        $this->Committee->recursive=-1;
        $name=$this->Committee->find('first',array('fields'=>array('name'),'conditions'=>array('id'=>$committee_id)));
        $name=str_replace(' ','_',$name['Committee']['name']);
        
        $this->cal($meetings,$name);
    }
    
    function create_usercal($userid,$username){
        require_once('vendors/iCalcreator.class.php');
        $this->Attendance->recursive=-1;
        $att=$this->Attendance->find('all',array('conditions'=>array('Attendance.deleted'=>0,'Attendance.user_id'=>$userid)));
        $meetings=$this->find('all',array('conditions'=>array('Meeting.deleted'=>0,'Meeting.id'=>set::extract($att,'{n}.Attendance.meeting_id'))));
        
        $this->cal($meetings,$username);
    }
    
    function cal($meetings,$name){
        $folder = WWW_ROOT . 'upload' . DS . 'ics'. DS;
        if (!is_dir($folder)) {
            $f = new Folder;
            $f->create(WWW_ROOT . 'upload' . DS . 'ics');
        }
        
        $dfile = WWW_ROOT . 'upload' . DS . 'ics'. DS . 'sequence.txt';
        if (file_exists($dfile)) {
            $handle = fopen($dfile, "r");
            $contents = fread($handle, filesize($dfile));
            fclose($handle);
            $sequence = $contents + 1;
        } else { 
            $sequence = 0;
        }
        $f = new File($dfile);
        $f->create($dfile);
        $f->write($sequence);
        
        $v = new vcalendar();
        $v->setConfig('URL',Router::url('/'.$name.'.ics'));
        //$v->setConfig('unique_id','dfafaf');
        $v->setProperty('method', 'PUBLISH');
        $v->setProperty('x-wr-calname', 'MyMeeting Calendar');
        $v->setProperty("X-WR-CALDESC", 'meetings');
        $v->setProperty("X-WR-TIMEZONE", 'Asia/Kuala_Lumpur');
        $this->calendar = $v;
        foreach($meetings as $meeting){
            $start = strtotime($meeting['Meeting']['meeting_date']);
        
            $vevent = new vevent();
            $end = $start + 2*60*60; // in seconds - 2 hours x 60 min x 60 sec
            $start = getdate($start);
            $a_start['year'] = $start['year'];
            $a_start['month'] = $start['mon'];
            $a_start['day'] = $start['mday'];
            $a_start['hour'] = $start['hours'];
            $a_start['min'] = $start['minutes'];
            $a_start['sec'] = $start['seconds'];
            $vevent->setProperty('dtstart', $a_start);
            
            $end = getdate($end);
            $e_start['year'] = $end['year'];
            $e_start['month'] = $end['mon'];
            $e_start['day'] = $end['mday'];
            $e_start['hour'] = $end['hours'];
            $e_start['min'] = $end['minutes'];
            $e_start['sec'] = $end['seconds'];
            //$vevent->setProperty('dtend', date('Ymd', $end), array('VALUE'=>'DATE'));
            $vevent->setProperty('dtend', $e_start);
            $vevent->setProperty('summary', $meeting['Meeting']['meeting_title'].','.$meeting['Meeting']['meeting_num']);
            $vevent->setProperty('description', __('See details',true).' http://'.$_SERVER['SERVER_NAME'].Router::url('/'.$meeting['Committee']['short_name'].'/meetings/view/'.$meeting['Meeting']['id']));
            $vevent->setProperty('sequence',$sequence);
            $extra=array('UID'=>'/'.$meeting['Committee']['short_name'].'/meetings/view/'.$meeting['Meeting']['id'].'@mm.com', 'location'=>$meeting['Meeting']['venue']);
            foreach($extra as $key=>$value){
                $vevent->setProperty($key, $value);
            }
        
            $this->calendar->setComponent($vevent);
        }
        
        $this->calendar->saveCalendar($folder ,$name.'.ics',false);
        
        return false;
    }
    
    /*
     * role - 3: member, 2: chairperson, 1: secretariats
     */ 
    function getMeetingsPerUser($userid,$role='3'){
        $this->unbindModel(array('hasMany'=>array('Decision','Todo','Notification'),'hasAndBelongsToMany'=>array('User')),false);
        $this->Behaviors->detach('MultiFile');
        $this->Behaviors->detach('Comment');
        $options['joins'] = array(
            array('table' => 'attendances',
                'alias' => 'Attendance',
                'type' => 'INNER',
                'conditions' => array(
                    'Attendance.meeting_id = Meeting.id',
                    'Attendance.user_id='.$userid,
                    'Attendance.attend_as='.$role
                )
            )
        );

        $options['fields'] = array('Committee.short_name','Meeting.id','Meeting.meeting_title','Meeting.meeting_num');
        //$options['order'] = array('Membership.order_id ASC');

        $meetings = $this->find('all', $options);
        if (count($meetings)) return $meetings;
        else return false;
    }
    
    //the user who had been receive the inivation letter
    function prev_invited_users($data){
        $this->data=$data;
        //prev_invited_users are those statuses are still involved in meeting
        $prev_invited_users_email=Set::extract($this->Notification->find('all',array('field'=>'to','conditions'=>array('meeting_id'=>$this->data['Meeting']['id'],'notification_sent'=>1,'type'=>array('invite','change','uninvite')))),'{n}.Notification.to');
        $n=count($prev_invited_users_email);
        //the user who receive the email 
        $prev_invited_users = Set::extract($this->User->find('all',array('conditions'=>array('email'=>$prev_invited_users_email))),'{n}.User.id');
        //the uninvited user
        $prev_uninvite=array();
        for($i=0;$i<$n;++$i){
            $prev_invited_users_notify[$i]=$this->Notification->find('first',array('fields'=>array('to','data','type'),'conditions'=>array('meeting_id'=>$this->data['Meeting']['id'],'notification_sent'=>1,'Notification.to'=>$prev_invited_users_email[$i],'type'=>array('invite','change','uninvite')),'order'=>'Notification.notification_date desc'));
            if ($prev_invited_users_notify[$i]['Notification']['type']=='uninvite'){
                $prev_uninvite[]=$prev_invited_users[$i];
            }
        }
        //minus the uninvited user from prev_invited_users
        return array_diff($prev_invited_users,$prev_uninvite);
    }
    
    function updatestatus(){
		$yesterday[0]=date('Y-m-d H:i:s',mktime(0, 0, 0, date('m'), date('d')-1, date('Y')));
		$yesterday[1]=date('Y-m-d H:i:s',mktime(23, 59, 59, date('m'), date('d')-1, date('Y')));
		$userstatuses=$this->Decision->Userstatus->find('all',array('conditions'=>array('Userstatus.created>="'.$yesterday[0].'"','Userstatus.created<="'.$yesterday[1].'"')));
		$groupstatuses=$this->Decision->Groupstatus->find('all',array('conditions'=>array('Groupstatus.created>="'.$yesterday[0].'"','Groupstatus.created<="'.$yesterday[1].'"')));
		
        if(!empty($userstatuses)){
			foreach( $userstatuses as $u=>$userstatus){
				$userstatus=am($userstatus,$this->find('first',array('contain'=>false,'conditions'=>array('id'=>$userstatus['Decision']['meeting_id']))));
				$updater=$this->User->read('name',$userstatus['Userstatus']['updater']);
				$userstatus['Updater']=$updater['User']['name'];
				$userstatus['Status']['user']=$userstatus['User']['name'];
				$userstatus['Status']['description']=$userstatus['Userstatus']['description'];
				//$userstatus['Link']['decision']=array('committee'=>urlencode($userstatus['Committee']['short_name']),'controller'=>'decisions','action'=>'view','decisionid'=>$userstatus['Decision']['id']);
				$userstatus['Link']['decision']='/'.$userstatus['Committee']['short_name'].'/decisions/view/'.$userstatus['Decision']['id'];
			
				$secretariat=$this->Attendance->find('all',array('conditions'=>array('Attendance.attend_as'=>1,'Attendance.meeting_id'=>$userstatus['Meeting']['id'])));
				if(!empty($secretariat)){
					foreach ($secretariat as $sec){
						$recipient[$sec['User']['id']][]=$userstatus;
						$user[$sec['User']['id']]=$sec['User'];
					}
				}
			}
		}
		
		if(!empty($groupstatuses)){
			foreach( $groupstatuses as $g=>$groupstatus){
				$groupstatus=am($groupstatus,$this->find('first',array('contain'=>false,'conditions'=>array('id'=>$groupstatus['Decision']['meeting_id']))));
				$groupstatus['Status']=$groupstatus['Groupstatus'];
				$groupstatus['Status']['user']=$groupstatus['Group']['name'];
				$updater=$this->User->read('name',$groupstatus['Groupstatus']['user_id']);
				$groupstatus['Updater']=$updater['User']['name'];
				//$groupstatus['Link']['decision']=array('committee'=>urlencode($groupstatus['Committee']['short_name']),'controller'=>'decisions','action'=>'view','decisionid'=>$groupstatus['Decision']['id']);
				$groupstatus['Link']['decision']='/'.$groupstatus['Committee']['short_name'].'/decisions/view/'.$groupstatus['Decision']['id'];
			
				$secretariat=$this->Attendance->find('all',array('conditions'=>array('Attendance.attend_as'=>1,'Attendance.meeting_id'=>$groupstatus['Meeting']['id'])));
				if(!empty($secretariat)){
					foreach ($secretariat as $sec){
						$recipient[$sec['User']['id']][]=$groupstatus;
						$user[$sec['User']['id']]=$sec['User'];
					}
				}
			}
		}
		
		if(!empty($userstatus)){
			$dec['Meeting']=$userstatus['Meeting'];
		}elseif(!empty($groupstatus)){
			$dec['Meeting']=$groupstatus['Meeting'];
		}
        
        if(!empty($dec['Meeting'])){
			$this->Template=& ClassRegistry::init('Template');
			$template=$this->Template->processTemplate('update status',$dec);
			$pos1=strpos($template['Template']['template'],'%%content to repeat');
			$pos2=strpos($template['Template']['template'],'content to repeat%%');
			$len=strlen('%%content to repeat');
			$content_repeat=substr($template['Template']['template'],$pos1+$len,$pos2-$pos1-$len);
		
		
			foreach($recipient as $userid=>$status){
				$template1=$template;
				$content='';
				foreach($status as $s){
					$content.=$this->replacetemplate($content_repeat,$s);
				}
				$template1['Template']['template']=str_replace('%%content to repeat'.$content_repeat.'content to repeat%%',$content,$template1['Template']['template']);
				$template1['Template']['template']=str_replace('http://http://','http://',$template1['Template']['template']);
                $this->sendEmail($dec['Meeting'],$template1,$user[$userid],Null);
			}
		}
	}
    
}
?>
